package com.aterrizar.aerolinea;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.aterrizar.asiento.Asiento;
import com.aterrizar.exception.CompraNoRealizadaException;
import com.aterrizar.exception.ReservaNoRealizadaException;
import com.aterrizar.sistema.Aterrizar;
import com.aterrizar.usuario.Usuario;
import com.lanchita.AerolineaLanchita;
import com.lanchita.excepciones.EstadoErroneoException;

public class Lanchita implements Aerolinea {

	private static final Lanchita INSTANCE = new Lanchita();
	private Integer porcentaje;
	private Map<String, String> mapa_ciudades;
	private Map<String, String> mapa_ciudades_lanchita;

	private AerolineaLanchita aerolineaLanchita;

	private Lanchita() {
		this.aerolineaLanchita = AerolineaLanchita.getInstance();
		mapa_ciudades = new HashMap<String, String>();
		mapa_ciudades.put("La Rioja", "_LR");
		mapa_ciudades.put("Buenos Aires", "_BS");
		mapa_ciudades.put("Nueva York", "_NY");
		mapa_ciudades.put("Los Angeles", "SLA");
		mapa_ciudades.put("Ezeiza", "EZE");
		mapa_ciudades.put("Estados Unidos", "USA");
		mapa_ciudades.put("Peru", "PER");
		mapa_ciudades.put("Usuahia", "USH");
		mapa_ciudades.put("Aeroparque", "AEO");

		mapa_ciudades_lanchita = new HashMap<String, String>();
		mapa_ciudades_lanchita.put("_LR", "La Rioja");
		mapa_ciudades_lanchita.put("_BS", "Buenos Aires");
		mapa_ciudades_lanchita.put("_NY", "Nueva York");
		mapa_ciudades_lanchita.put("SLA", "Los Angeles");
		mapa_ciudades_lanchita.put("EZE", "Ezeiza");
		mapa_ciudades_lanchita.put("USA", "Estados Unidos");
		mapa_ciudades_lanchita.put("PER", "Peru");
		mapa_ciudades_lanchita.put("USH", "Usuahia");
		mapa_ciudades_lanchita.put("AEO", "Aeroparque");
	}

	public static void establecerPorcentaje(Integer porcentaje) {
		INSTANCE.setPorcentaje(porcentaje);
	}

	@Override
	public Set<Asiento> buscar(Usuario usuario, String origen, String destino,
			String fecha, String horaSalida, String horaLlegada) {

		String origenLanchita = null;
		String destinoLanchita = null;

		if (origen != null && destino != null) {
			origenLanchita = mapa_ciudades.get(origen);
			destinoLanchita = mapa_ciudades.get(destino);
		}
		// Asientos que tienen la fecha ingresada como fecha de salida
		String[][] asientosConIgualFechaSalida = aerolineaLanchita
				.asientosDisponibles(origenLanchita, destinoLanchita, fecha,
						horaSalida, null, horaLlegada);

		// Asientos que tienen la fecha ingresada como fecha de llegada
		String[][] asientosConIgualFechaLlegada = aerolineaLanchita
				.asientosDisponibles(origenLanchita, destinoLanchita, null,
						horaSalida, fecha, horaLlegada);

		String[][] asientos = concatenar_asientos(asientosConIgualFechaSalida,
				asientosConIgualFechaLlegada);
		Set<Asiento> asientosDisponibles = new HashSet<Asiento>();
		asientosDisponibles = arrayDeAsientosToAsientos(usuario, asientos);
		return asientosDisponibles;
	}

	private Set<Asiento> arrayDeAsientosToAsientos(Usuario usuario,
			String[][] arrayAsientos) {
		Set<Asiento> asientos = new HashSet<Asiento>();
		for (String[] asiento : arrayAsientos) {
			Asiento nuevoAsiento = arrayAsientoToAsiento(asiento);
			BigDecimal recargo = usuario != null ? new BigDecimal(usuario
					.getTipoUsuario().getRecargo()) : new BigDecimal(0);
			nuevoAsiento.setPrecio(nuevoAsiento.getPrecio()
					.multiply(new BigDecimal(this.getPorcentaje().intValue()))
					.divide(new BigDecimal(100)).add(recargo));
			asientos.add(nuevoAsiento);
		}
		return asientos;
	}

	private Asiento arrayAsientoToAsiento(String[] asiento) {
		Asiento nuevoAsiento = new Asiento(asiento[0], new BigDecimal(
				asiento[1]), asiento[2], asiento[3], asiento[10], asiento[11],
				asiento[6], asiento[7], mapa_ciudades_lanchita.get(asiento[8]),
				mapa_ciudades_lanchita.get(asiento[9]), this);
		return nuevoAsiento;
	}

	@Override
	public void comprar(String codigo, String dni) {
		try {
			aerolineaLanchita.comprar(codigo);
		} catch (EstadoErroneoException e) {
			throw new CompraNoRealizadaException();
		}
	}

	@Override
	public void reservar(String codigo, String dni) {
		try {
			aerolineaLanchita.reservar(codigo, dni);
		} catch (EstadoErroneoException e) {
			throw new ReservaNoRealizadaException();
		}
	}

	@Override
	public Integer getPorcentaje() {
		return porcentaje;
	}

	@Override
	public void setPorcentaje(Integer porcentaje) {
		this.porcentaje = porcentaje;
	}

	public static Lanchita getInstance() {
		return INSTANCE;
	}

	@Override
	public String adaptarClase(String clase) {
		return null;
	}

	public String adaptarUbicacion(String ubicacion) {
		return null;
	}

	private String[][] concatenar_asientos(String[][] A, String[][] B) {
		if (A != null && B != null) {
			String[][] C = new String[A.length + B.length][];
			System.arraycopy(A, 0, C, 0, A.length);
			System.arraycopy(B, 0, C, A.length, B.length);
			return C;
		} else
			return null;
	}

	public void actualizarReservasVencidas(String[][] listaDeAsientos) {
		Aterrizar.getInstance().removerCaducados(
				new ArrayList<Asiento>(arrayDeAsientosToAsientos(null,
						listaDeAsientos)));

	}

	public AerolineaLanchita getAerolineaLanchita() {
		return aerolineaLanchita;
	}

	public void setAerolineaLanchita(AerolineaLanchita aerolinea) {
		this.aerolineaLanchita = aerolinea;
	}

	@Override
	public String getNombre() {
		return this.getClass().getSimpleName();
	}
}